package org.naxx.security.datatype.impl;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.naxx.security.datatype.DataType;
import org.naxx.security.datatype.DataTypeDefinitionLoader;
import org.naxx.security.datatype.DataTypeResolver;
import org.naxx.security.util.Assert;

public final class DataTypeResolverImpl implements DataTypeResolver {
	
	// TODO unify this into multi-key map
	
	// key is data type uri
	private Map<String, DataType> dataTypes;
	private Map<Integer, DataType> dTypes;
	private DataTypeDefinitionLoader dataTypeDefinitionLoader;
	
	public void setDataTypeDefinitionLoader(
			DataTypeDefinitionLoader dataTypeDefinitionLoader) {
		this.dataTypeDefinitionLoader = dataTypeDefinitionLoader;
	}

	public void configure() {
		this.initDataTypeRepository();
	}

	public DataType resolveDataType(Integer id) {
		DataType result = this.dTypes.get(id);
		if(result == null) {
			throw new IllegalArgumentException("Unable to resolve type id '" 
					+ id + "' to data type");
		}
		return result;
	}

	public DataType resolveDataType(String typeUri) {
		DataType result = this.dataTypes.get(typeUri);
		if(result == null) {
			throw new IllegalArgumentException("Unable to resolve type uri '" 
					+ typeUri + "' to data type");
		}
		return result;
	}
	
	public Map<String, DataType> getDefinedDataTypes() {
		return Collections.unmodifiableMap(this.dataTypes);
	}

	private void initDataTypeRepository() {
		Set<DataType> dataTypes = this.dataTypeDefinitionLoader.loadDataTypeDefinitions();
		this.dataTypes = new HashMap<String, DataType>(dataTypes.size());
		this.dTypes = new HashMap<Integer, DataType>(dataTypes.size());
		for(DataType dataType : dataTypes) {
			Assert.assertNull(this.dataTypes.put(dataType.getUri(), dataType), 
					"Duplicate data type defined with uri '" + dataType.getUri() + "'");

			Assert.assertNull(this.dTypes.put(dataType.getId(), dataType), 
					"Duplicate data type defined with id '" + dataType.getUri() + "'");
		}
	}
}
